import { existsSync, readdirSync, readFileSync, statSync, unlinkSync, writeFileSync } from "fs";
import { EncriptTool } from "./utils/EncriptTool";
import { Handler } from "../../core/Handler";
import { extname, join } from "path";
import { ApplyJsb } from "./utils/ApplyJsb";
import { ApplyWeb } from "./utils/ApplyWeb";

/**构建类型 */
var BuildTypeEnum = {
    web_desktop: 0,
    web_mobile: 1,
    jsb_link: 2,
};

export default class Helper extends Handler {

    /**加密文件后缀支持目录 */
    root_path_List = ["web-desktop", "web-mobile", "jsb-link"];

    /**加密后缀名排除列表 */
    encript_ignore_extList = ["mp3", "ogg", "wav", "m4a", "jsc", "bin"];

    /**加密实现工具类 */
    _encriptTool = new EncriptTool();

    /**计数 */
    encriptFinishNum = 0;

    private _config: EncryptResourcesConfig = null!;
    /**@description 加密配置 */
    get config() {
        this.encriptFinishNum = 0;
        if (!this._config) {
            this._config = this.defaultConfig;
        }
        return this._config;
    }

    set config(v) {
        this._config = v;
    }

    private get defaultConfig(): EncryptResourcesConfig {
        return {
            encryptSign: "QuickFramework",
            encryptKey: "QuickFramework",
            srcLabel: "",
            buildType: 2,
        };
    }

    checkBuildDir(fullPath: string): boolean {
        let isValid = false;
        if (existsSync(fullPath)) {
            let pathParts = fullPath.split("/");
            if (pathParts.length > 0) {
                let lastPart = pathParts[pathParts.length - 1];
                if (this.root_path_List.includes(lastPart)) {
                    isValid = true;
                    this._config.buildType = this.root_path_List.indexOf(lastPart);
                    if (this._config.buildType === BuildTypeEnum.jsb_link) {
                        this.encript_ignore_extList = ["mp3", "ogg", "wav", "m4a", "jsc", "bin"];
                    } else if (this._config.buildType === BuildTypeEnum.web_mobile || this._config.buildType === BuildTypeEnum.web_desktop) {
                        ///web平台，只加密文本、图片
                        this.encript_ignore_extList = [
                            "js", "jsc",
                            "mp3", "ogg", "wav", "m4a",
                            "font", "eot", "ttf", "woff", "svg", "ttc",
                            "mp4", "avi", "mov", "mpg", "mpeg", "rm", "rmvb"
                        ];
                    }
                } else {
                    this.logger.error(`加密目录不在支持列表中 : ${lastPart}`);
                }
            } else {
                this.logger.error(`加密目录路径格式错误 : ${fullPath}`);
            }
        }
        if (!isValid) {
            this.logger.error(`加密目录不存在 : ${fullPath}`);
            return false;
        }
        return isValid;
    }

    encodeFile(filePath: string) {
        let ext = extname(filePath);
        if (this.encript_ignore_extList.includes(ext)) {
            this.logger.log(`跳过加密文件 : ${filePath}`);
            return;
        }
        let inBuffer = readFileSync(filePath);
        if (this._encriptTool.checkIsEncripted(inBuffer.buffer)) {
            this.logger.log(`文件已经加密 : ${filePath}`);
            return;
        }
        this.logger.log(`开始加密文件 : ${filePath}`);
        let outBuffer = this._encriptTool.encodeArrayBuffer(inBuffer.buffer);
        unlinkSync(filePath); // 删除原文件
        writeFileSync(filePath, String(outBuffer)); // 写入加密后的文件
        this.encriptFinishNum++;
    }

    encriptDir(dirPath: string) {
        if (!existsSync(dirPath)) {
            this.logger.error(`目录不存在 : ${dirPath}`);
            return;
        }
        let files = readdirSync(dirPath);
        files.forEach(file => {
            let filePath = join(dirPath, file.toString());
            let stat = statSync(filePath);
            if (stat.isDirectory()) {
                this.encriptDir(filePath); // 递归处理子目录
            } else {
                this.encodeFile(filePath); // 加密文件
            }
        });
    }

    replaceResources() {
        this.logger.log(`开始进行资源加密，加密指定目录 : ${this.config.srcLabel}`);
        this._encriptTool.setKeySign(this.config.encryptKey, this.config.encryptSign);
        let assetsPath = join(this.config.srcLabel, "assets");
        this.encriptDir(assetsPath);
        if (this._config.buildType === BuildTypeEnum.jsb_link) {
            // 对jsb-link平台的特殊处理
            new ApplyJsb(this._config.encryptSign, this._config.encryptKey);
            let jsbAdapterPath = join(this.config.srcLabel, "jsb-adapter");
            let srcPath = join(this.config.srcLabel, "src");
            let mainJsPath = join(this.config.srcLabel, "main.js");
            this.encriptDir(jsbAdapterPath);
            this.encriptDir(srcPath);
            this.encodeFile(mainJsPath);
        } else if (this._config.buildType === BuildTypeEnum.web_mobile || this._config.buildType === BuildTypeEnum.web_desktop) {
            // 对web平台的特殊处理
            new ApplyWeb(this._config.encryptSign, this._config.encryptKey, this.config.srcLabel);
        }
        this.logger.log(`加密完成，共加密文件 : ${this.encriptFinishNum} 个`);
    }
}

export const helper = new Helper();